#include <iostream>
#include <string>
#include <vector>
#include <pthread.h>
#include <unistd.h>

using namespace std;

const int threadnum = 5;
int wake = 1;
// 静态初始化条件变量和互斥锁
//pthread_cond_t gcond = PTHREAD_COND_INITIALIZER; // 条件变量
//pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁

pthread_cond_t gcond;
pthread_mutex_t gmutex;

void *thread_func(void *args)
{
    string name = static_cast<const char *>(args);
    // 1. 加锁。一个线程持有锁后其它线程都会在此被阻塞等待
    pthread_mutex_lock(&gmutex);
    // 2. 使用条件变量（一般条件变量是在加锁和解锁之间使用的）
    if (wake)
    {
        pthread_cond_wait(&gcond, &gmutex); 
    }
    cout << "当前被叫醒的线程是: " << name << endl;
    // 3. 解锁
    pthread_mutex_unlock(&gmutex);
    return nullptr;
}

int main()
{
    // 动态初始化条件变量和互斥锁
    pthread_mutex_init(&gmutex, nullptr);  
    pthread_cond_init(&gcond, nullptr); 
    //创建一批线程
    vector<pthread_t> tids;
    for (int i = 0; i < threadnum; i++)
    {
        char *name = new char[64];
        snprintf(name, 64, "thread-%d", i + 1); 
        pthread_t tid;
        int n = pthread_create(&tid, nullptr, thread_func, name);
        if (n == 0)
        {
            cout << "create success: " << name << endl;
            tids.emplace_back(tid);
        }
        // sleep休眠是为了保证线程调度的顺序按照线程创建的顺序进行
        sleep(1);
    }
    // 依次唤醒一个线程
    for (int i = 0; i < threadnum; i++)
    {
        // 唤醒一个线程(唤醒是随机的)
        pthread_cond_signal(&gcond);
        cout << "唤醒线程" << endl;
        sleep(1);
    }

    // 唤醒所有的线程
    // pthread_cond_broadcast(&gcond);
    // wake = 0;

    // 释放线程资源
    for (auto &tid : tids)
    {
        pthread_join(tid, nullptr);
    }
    // 动态初始化条件变量和互斥锁时需使用下面函数销毁
    pthread_mutex_destroy(&gmutex);  
    pthread_cond_destroy(&gcond);  
    return 0;
}